﻿
using System;
using System.Web;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using MvcScriptManager.UniqueKeyEncoding;

namespace MvcScriptManager.Tests.UniqueKeyEncoding
{
	/// <summary>
	/// Summary description for UniqueKeyOneWayHashTests
	/// </summary>
	[TestClass]
	public class UniqueKeyOneWayHashTests
	{
		/// <summary>
		/// Gets or sets the test context which provides
		/// information about and functionality for the current test run.
		/// </summary>
		public TestContext TestContext { get; set; }

		private UniqueKeyOneWayHash encoder;

		private HttpContext dummyHttpContext;

		[TestInitialize]
		public void Initialize()
		{
			encoder = new UniqueKeyOneWayHash();

			HttpRequest httpRequest = new HttpRequest(null, "http://localhost/", null);
			HttpResponse httpResponse = new HttpResponse(null);
			dummyHttpContext = new HttpContext(httpRequest, httpResponse);
		}

		[TestMethod]
		public void TestEncodeUniqueKey()
		{
			ScriptReference reference = new ScriptReference
			{
				Path = "/content/sample.js",
				EnableCrunching = true,
				ResourceAssembly = "SampleWeb",
				ResourceName = "SampleWeb.Sample",
				ResourceTypeName = "Sample"
			};

			string uniqueKey = encoder.EncodeUniqueKey(reference, dummyHttpContext);

			Assert.IsNotNull(uniqueKey);

			Assert.AreEqual("5f7594aa", uniqueKey);
		}

		/// <summary>
		/// Tests that encoding a unique key, then decoding it returns the same script reference
		/// </summary>
		[TestMethod]
		public void TestEncodeDecodeReturnsSameResult()
		{
			ScriptReference reference = new ScriptReference
			{
				Path = "/content/encodedecodetest.js",
				EnableCrunching = false,
				ResourceAssembly = "SampleWeb",
				ResourceName = "SampleWeb.Sample",
				ResourceTypeName = "Sample"
			};

			string uniqueKey = encoder.EncodeUniqueKey(reference, dummyHttpContext);

			Assert.IsNotNull(uniqueKey);

			ScriptReference actual = encoder.DecodeUniqueKey(uniqueKey, dummyHttpContext);

			Assert.IsNotNull(actual);

			Assert.AreEqual(reference.Path, actual.Path, "Path");
			Assert.AreEqual(reference.EnableCrunching, actual.EnableCrunching, "EnableCrunching");
			Assert.AreEqual(reference.ResourceAssembly, actual.ResourceAssembly, "ResourceAssembly");
			Assert.AreEqual(reference.ResourceName, actual.ResourceName, "ResourceName");
			Assert.AreEqual(reference.ResourceTypeName, actual.ResourceTypeName, "ResourceTypeName");
		}

		[TestMethod]
		public void TestDecodeUniqueKey()
		{
			ScriptReference expected = new ScriptReference
			{
				Path = "/content/sample.js",
				EnableCrunching = true,
				ResourceAssembly = "SampleWeb",
				ResourceName = "SampleWeb.Sample",
				ResourceTypeName = "Sample"
			};

			const string uniqueKey = "5f7594aa";

			//ensure our reference is present in the local cache
			encoder.EncodeUniqueKey(expected, dummyHttpContext);

			ScriptReference actual = encoder.DecodeUniqueKey(uniqueKey, dummyHttpContext);

			Assert.IsNotNull(actual);

			Assert.AreEqual(expected.Path, actual.Path);
			Assert.AreEqual(expected.EnableCrunching, actual.EnableCrunching);
			Assert.AreEqual(expected.ResourceAssembly, actual.ResourceAssembly);
			Assert.AreEqual(expected.ResourceName, actual.ResourceName);
			Assert.AreEqual(expected.ResourceTypeName, actual.ResourceTypeName);
		}

		[TestMethod]
		[ExpectedException(typeof(InvalidOperationException))]
		public void TestDecodeUniqueKeyWithUnknownKeyThrowsException()
		{
			const string uniqueKey = "abcd";

			encoder.DecodeUniqueKey(uniqueKey, dummyHttpContext);
		}
	}
}